package com.is2.patchinglife.manager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

import com.facebook.FacebookException;
import com.facebook.FacebookOperationCanceledException;
import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.Request.Callback;
import com.facebook.RequestAsyncTask;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.Session.NewPermissionsRequest;
import com.facebook.Session.OpenRequest;
import com.facebook.Session.StatusCallback;
import com.facebook.SessionLoginBehavior;
import com.facebook.SessionState;
import com.facebook.model.GraphObject;
import com.facebook.widget.WebDialog;
import com.facebook.widget.WebDialog.OnCompleteListener;

public class FacebookManager {
	
	public static String fbUserID = null;
	public static String fbEmail = null;
	private FacebookManager(){}
	// callback to call initFacebookSession [used by loginFacebook]
	private static Session.StatusCallback login_callback = new Session.StatusCallback() {
		@Override
		public void call(Session session, SessionState state, Exception exception) {
			
			if(session.isOpened()){
				initFacebookSession();
				
			}else if(exception!=null){
				Session.setActiveSession(new Session(LocalDataManager.getContext()));	// create new session
			}
		}
	}; 
	
	// callback to analyze FQL query results, setting fbUserID and fbEmail [used by initFacebookSession]
	private static Request.Callback request_callback = new Callback() {
		@Override
		public void onCompleted(Response response) {
			
			try {
	
				GraphObject graphObject = response.getGraphObject();		// request result
				String jsonString = ""+graphObject.getProperty("data");		// get obtained datas
				
				// parse JSON results
				JSONArray jsonData = new JSONArray(jsonString);
				fbEmail = jsonData.getJSONObject(0).getString("email");
				fbUserID = jsonData.getJSONObject(0).getString("uid");
				
				// setting textbox in ProfileActivity with email
				Activity profile = ActivityManager.getInstance().get("ProfileActivity");
				if (profile != null){
					EditText txt = (EditText)profile.findViewById(com.is2.patchinglife.R.id.profileTxtFacebook);
					if(txt!=null)txt.setText(fbEmail);
				}
								
			} catch (JSONException e) {
				Log.e("FacebookManager", "request_callback: JSON ERROR");
				e.printStackTrace();
			}
		}
	};
	
	
	/** Performs Facebook login **/
	public static SessionState loginFacebook(Activity _activity, StatusCallback _callback, List<String> _readPermission){
		
		if(_callback == null) _callback = login_callback;	// setting callback
		if(_readPermission == null) _readPermission = Arrays.asList("email","basic_info");	//setting read permission
		
		Session session = Session.getActiveSession();
		
		if(!session.isOpened()){		// active session check

			OpenRequest openRequest = new OpenRequest(_activity)	// facebook request creation
			.setLoginBehavior(SessionLoginBehavior.SUPPRESS_SSO)	// setting login behavior.
																	// SUPPRESS_SSO: ask for username and pwd indipendently from device FB application
			
			.setCallback(_callback)									// setting callback [called after connection]
			.setPermissions(_readPermission);	// setting permissions
																	// email: allow query to user email
																	// basic_info: allow query to allow query to basic infos such as name, surname, birth date,...

			session.openForRead(openRequest);	// session opening
			
		}
		
		return session.getState();
	}

	
	/** Asks for Facebook infos [query] **/
	public static void initFacebookSession(){
		
		Session session = Session.getActiveSession();
		if(session!=null){
			if(session.isOpened()){
				String fqlQuery = "Select email, uid FROM user WHERE uid=me();";
				getResultFQLQuery(fqlQuery,request_callback);
			}
		}
	}
	
	/** Makes an FQL asyncronous query to FB database **/
	public static RequestAsyncTask getResultFQLQuery(String queryString, Callback _callback){
		String fqlQuery = queryString;	// FQL query
		
		// setting parameters
		Bundle params = new Bundle();
		params.putString("q", fqlQuery);				// request type [how to parse fqlQuery]
		Session session = Session.getActiveSession();	// get active session
		
		// setting request
		Request request = new Request( 	session,
										"/fql",                         
										params,                         
										HttpMethod.GET,                 
										_callback
									); 

		RequestAsyncTask requestAsyncTask = request.executeAsync();		// start async request

		return requestAsyncTask;
	}


	/** Publishes something on Facebook wall
	 * _activity: activity which called the method
	 * _name: post name
	 * _caption: post shown title
	 * _description: post content
	 * _link: link [in case of post clicking]
	 * _urlImg: post image
	 * _close: flag [close connection after publishing]
	 **/
	public static boolean publishSomething( final Activity _activity, String _name, String _caption, 
											String _description, String _urlPage, String _urlImg, 
											final boolean _close) {

		if(Session.getActiveSession().isOpened()){
			
			setPublishPermission(_activity, Arrays.asList("publish_actions")); 	// setting permissions
			
			// post creation
			Bundle params = new Bundle();
			params.putString("name", _name);
			params.putString("caption", _caption);
			params.putString("description", _description);
			params.putString("link", _urlPage);
			params.putString("picture", _urlImg);

			// Facebook SDK WebDialog to show sharing window
			WebDialog feedDialog = (
					new WebDialog.FeedDialogBuilder(_activity, Session.getActiveSession(), params))
							.setOnCompleteListener(new OnCompleteListener() {

								@Override
								public void onComplete(Bundle values, FacebookException error) {
									if (error == null) {
										// when the story is posted, echo the success and the post ID.
										final String postId = values.getString("post_id");
										if (postId != null) {
											Toast.makeText(_activity,
													"Publish completed",
													Toast.LENGTH_SHORT).show();
										} else {
											// user clicked the Cancel button
											Toast.makeText(_activity.getApplicationContext(), 
													"Publish cancelled", 
													Toast.LENGTH_SHORT).show();
										}
									} else if (error instanceof FacebookOperationCanceledException) {
										// user clicked the "x" button
										Toast.makeText(_activity.getApplicationContext(), 
												"Publish cancelled", 
												Toast.LENGTH_SHORT).show();
									} else {
										// generic error
										Toast.makeText(_activity.getApplicationContext(), 
												"Posting error", 
												Toast.LENGTH_SHORT).show();
									}
									
									if(_close){
										FacebookManager.logoutFacebook();
									}
								}
							})
							.build();	// build dialog
			
			feedDialog.show();			// show dialog
			
			return true;
		
		}else{
			return false;
		}
	}
	
	/** Logout from Facebook with alert dialog **/
	public static void logoutWithRequest(final Activity _activity){
		
		// setting alert dialog
		AlertDialog.Builder builder = new AlertDialog.Builder(_activity);
		builder.setTitle("ALERT");
		builder.setMessage("Do you want to logout account " + fbEmail + "?");

		// setting "no" button
		builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				return;
			}
		});

		// setting "yes" button
		builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				logoutFacebook();		// logout from Facebook
				return;
			}
		});

		AlertDialog alert = builder.create();
		alert.show();
	}
	
	
	/** Logout from Facebook **/
	public static SessionState logoutFacebook(){
		
		Session session = Session.getActiveSession(); 
		if(session!=null){
			// reset connection
			session.closeAndClearTokenInformation(); 	// close FB connection and delete memorized token
			fbUserID = null;
			fbEmail = null;
			
			session = new Session(LocalDataManager.getContext());
			Session.setActiveSession(session);

			return session.getState();	// return session state
		}else{
			
			session = new Session(LocalDataManager.getContext());
			Session.setActiveSession(session);
			return session.getState();	// return session state
			
		}
		
	}
	
	
	
	/** :::::::::: UTILITY METHODS :::::::::: **/ 
	
	/** Reinitializes session to allow writing [wall publishing] **/
	public static void setPublishPermission(Activity _activity, List<String> _permissions){
		
		NewPermissionsRequest newPermissionsRequest = checkPermission(_activity, _permissions);
		
		if(newPermissionsRequest!=null){
			Session session = Session.getActiveSession();
			session.requestNewPublishPermissions(newPermissionsRequest);	// create session with publish permission
		}
		
	}
	
	
	/** Reinitializes session to allow reading **/
	public static void setReadSession(Activity _activity, List<String> _permissions){

		NewPermissionsRequest newPermissionsRequest = checkPermission(_activity, _permissions);
		
		if(newPermissionsRequest!=null){
			Session session = Session.getActiveSession();
			session.requestNewReadPermissions(newPermissionsRequest);		// create session with read permission
		}
		
	}

	
	/** Check current session permissions **/
	public static NewPermissionsRequest checkPermission (Activity _activity, List<String> _permissions){

		Session session = Session.getActiveSession();
		List<String> actualPermissions = session.getPermissions();	// get current session permissions
		List<String> permissionsToSet = new ArrayList<String>();

		// check new permissions
		boolean newPerm = false;
		for(String perm:_permissions){
			if(!actualPermissions.contains(perm)){
				permissionsToSet.add(perm);
				newPerm = true;
			}
		}

		// check if new permissions have been specified
		if(newPerm){
			return new NewPermissionsRequest(_activity, permissionsToSet);		// return new permission request
		}else{
			return null;
		}
	}

}
